package edu.drexel.cs575.phw1.scale;

import java.util.ArrayList;
import java.util.List;

import listeners.TrayListener;
import listeners.WeightMechanismListener;

/**
 * Determines the weight of a <code>Weighable<code> item.
 * 
 * @author anthony
 *
 */
public class WeightMechanism implements TrayListener {
	//By default we'll use US unit of measure
	private UnitOfMeasure unitOfMeasure = UnitOfMeasure.US;
	private Tray tray;
	private List<WeightMechanismListener> listeners = new ArrayList<WeightMechanismListener>();
	private double tareMass;
	
	public WeightMechanism() {
		this.tray = new Tray();
		
		this.tray.addListener(this);
	}
	
	public void addItem(Weighable item) {
		this.tray.addItem(item);
	}
	
	public Weight getTotalWeight() {
		Weight weight = new Weight();
		double mass = getTotalMass();
		
		weight.setValue((mass - this.tareMass) * this.unitOfMeasure.getMultiplier());
		weight.setUnitOfMeasure(this.unitOfMeasure);
		
		return weight;
	}

	public void setTare() {
		this.tareMass = getTotalMass();
		
		System.out.println("WEIGHT_MECHANISM: Tare set.");
		notifyTareSetListeners();
	}
	
	public void removeItems() {
		this.tray.removeItems();
	}
	
	public void toggleUnits() {
		this.unitOfMeasure = (this.unitOfMeasure == UnitOfMeasure.US) ? UnitOfMeasure.METRIC : UnitOfMeasure.US;
		
		System.out.println("WEIGHT_MECHANISM: Units toggled.");
	}

	@Override
	public void itemAdded() {
		notifyItemAddedListeners();		
	}

	@Override
	public void itemsRemoved() {
		this.tareMass = 0;
		
		notifyItemsRemovedListeners();
	}
	
	public void addListener(WeightMechanismListener listener) {
		if (listener == null) {
			throw new IllegalArgumentException("Listener cannot be null");
		}
		
		this.listeners.add(listener);
	}
	
	private double getTotalMass() {
		List<Weighable> items = tray.getItemsInTray();
		double mass = 0;
		
		for(Weighable item : items) {
			mass += item.getMass();
		}
		
		return mass;
	}

	private void notifyItemAddedListeners() {
		for(WeightMechanismListener listener : listeners) {
			listener.itemAdded();
		}
	}
	
	private void notifyItemsRemovedListeners() {
		for(WeightMechanismListener listener : listeners) {
			listener.itemsRemoved();
		}
	}
	
	private void notifyTareSetListeners() {
		for(WeightMechanismListener listener : listeners) {
			listener.tareSet();
		}
	}
}
